enum RequestMethod {
	GET = 'GET',
	POST = 'POST',
	PUT = 'PUT',
	DELETE = 'DELETE',
	CONNECT = 'CONNECT',
	HEAD = 'HEAD',
	OPTIONS = 'OPTIONS',
	TRACE = 'TRACE'
}
type ToastIcon = 'success' | 'loading' | 'error' | 'none' | 'fail' | 'exception';

enum LocationType {
	Gcj02 = 'gcj02',
	Wgs84 = 'wgs84'
}
const deflang = uni.getStorageSync('systemdeflang') || 'zh-cn'; 
import tw from './lang/tw.json';//繁体文字配置文件
import en from './lang/en.json';//英文配置文件
const langs = {
	'zh-hk':tw,
	'zh-en':en
}
export default class Init {
	url : string;
	imgUrl : string;
	routing : string[];
	constructor({ url, intercept = false, routing = [] } : { url : string; intercept : boolean; routing : string[] }) {
		this.url = `${url}/api/`;
		this.imgUrl = `${url}/static/image/`
		this.routing = routing;
		if (intercept) this.interception()
	}
	/**
	 * lang 语言模块
	 * @param {String} txt 需要转换的文本
	 */
	lang(txt:string){
		if (deflang != 'zh-cn') {
			if (langs[deflang] && langs[deflang][txt]) {
				return langs[deflang][txt];
			}
		}
		return txt;
	}
	/**
	 * interception 路由拦截
	 * 在需要登录的页面进行判断拦截
	 * 注意这里不拦截 switchTab跳转模式需要自行处理
	 */
	interception() {
		let _this = this;
		const routingMethods = ['navigateTo', 'redirectTo', 'reLaunch'];
		const routerList = ['pages/index/index']; // 页面白名单 
		routingMethods.forEach((method) => {
			uni.addInterceptor(method, {
				invoke(args) {
					if (!_this.routing.includes(args.url.split('?')[0]) && !uni.getStorageSync('token')) {
						_this.loginModel()
						return false
					}
				}
			})
		})
		// 拦截网络请求
		uni.addInterceptor('request', {
			success: (res) => {
				if (res.data.status == 410000 || res.data.status == 410001 || res.data.status == 410002) {
					uni.removeStorageSync('token') //移除token
					let routes = getCurrentPages(); //获取页面路由栈
					// 判断当前的页面路由是否在在路由白名单 如果不在白名单 &&  不存在token 那么触发登录
					// #ifdef MP-TOUTIAO
					if (!_this.routing.includes(routes[routes.length - 1].route) && !uni.getStorageSync('token')) {
						_this.loginModel()
						return false
					}
					// #endif
					// != 'pages/index/index'
					// #ifndef MP-TOUTIAO
						if (!_this.routing.includes(routes[routes.length - 1].route) && !uni.getStorageSync('token')
							&& !routerList.includes(routes[routes.length - 1].route)) {
							_this.loginModel()
							return false
						}
					// #endif
				}
			}
		})
	}
	/**
	 * 登录模块
	 * 登录全部统一进入login页面
	 * 如果是H5公众号login也是必须要新建 通过lonig作为中转登录
	 */
	loginModel() {
		uni.reLaunch({
			url: '/pages/login/login'
		})
	}
	/**
	 * request 发起网络请求
	 * @property {string} url 网络请求地址
	 * @property {object} data 请求参数
	 * @property {object} header 请求头
	 * @property {string} method 请求方式
	 */
	async request({ url, data = {}, header = {}, method = RequestMethod.GET } : { url : string; data ?: object; header ?: object; method : RequestMethod }) : Promise<any> {
		let env = 'app'
		// #ifdef APP
		const Formtype = 'app'
		// #endif
		// #ifdef MP-WEIXIN
		const Formtype = 'routine'
		env = wx.getAccountInfoSync().miniProgram.envVersion
		// develop开发版、trial体验版、release正式版
		// #endif
		// #ifdef MP-TOUTIAO
		const Formtype = 'douyin'
		env = tt.getEnvInfoSync().microapp.envType
		// production线上版  development测试版  preview预览版
		// #endif
		// #ifdef H5
		const Formtype = 'wechat'
		// #endif

		try {
			const result = await uni.request({
				url,
				data,
				header: Object.keys(header).length ? header : {
					"Authori-zation": `Bearer ${uni.getStorageSync('token')}`,
					"Form-type": Formtype,
					// #ifndef H5
					env: env,
					// #endif
					"lang":deflang
				},
				method
			});
			// 一般是在网络请求出错才会触发，比如超时，断网
			if (result.statusCode !== 200) {
				this.hideloading()
				this.model({
					title: '温馨提示',
					content: `网络请求失败，状态码${result.statusCode}`,
					showCancel: false,
					confirmText: '我知道了'
				})
				return
			}
			if (result.data.status !== 200) return this.toast(result.data.msg)
			return result.data;
		} catch (error) {
			throw error;
		}
	}
	/**
	 * get 发起一个get的网络请求
	 * @property {string} url 接口地址
	 * @property {object} data 请求参数(可选)
	 * @property {object} header 请求头(可选)
	 */
	async get({ url, data, header } : { url : string; data ?: object; header ?: object }) : Promise<any> {
		const result = await this.request({
			url: `${this.url}${url}`,
			data: data,
			header: header,
			method: RequestMethod.GET
		});
		return result;
	}
	/**
	 * post 发起一个post的网络请求
	 * @property {string} url 接口地址
	 * @property {object} data 请求参数(可选)
	 * @property {object} header 请求头(可选)
	 */
	async post({ url, data, header } : { url : string; data ?: object; header ?: object }) : Promise<any> {
		const result = await this.request({
			url: `${this.url}${url}`,
			data: data,
			header: header,
			method: RequestMethod.POST
		});
		return result;
	}
	/**
	 * put 发起一个put的网络请求
	 * @property {string} url 接口地址
	 * @property {object} data 请求参数(可选)
	 * @property {object} header 请求头(可选)
	 */
	async put({ url, data, header } : { url : string; data ?: object; header ?: object }) : Promise<any> {
		const result = await this.request({
			url: `${this.url}${url}`,
			data: data,
			header: header,
			method: RequestMethod.PUT
		});
		return result;
	}
	/**
	 * toast 简短提示弹窗
	 * @property {string} title 提示内容
	 * @property {string} icon 提示的图标 默认none
	 */
	toast(title : string, icon : ToastIcon = 'none') : void {
		uni.showToast({
			title: title,
			icon
		});
	}
	/**
	 * loading 加载等待框
	 * @property {string} title 提示内容
	 * @property {boolean} mask 是否阻止穿透 默认false
	 */
	loading(title : string, mask : boolean = false) : void {
		uni.showLoading({
			title,
			mask
		});
	}
	/**
	 * hideloading 隐藏加载等待框
	 */
	hideloading() : void {
		uni.hideLoading();
	}
	/**
	 * model 确认对话框
	 * @property {string} title 对话框标题
	 * @property {string} content 对话框显示内容
	 * @property {boolean} showCancel 是否显示取消按钮默认true
	 * @property {string} confirmText 确认按钮的文字默认'确定'
	 * @property {string} cancelText 取消按钮的文字默认'取消'
	 */
	async model({
		title,
		content,
		showCancel = true,
		confirmText = '确定',
		cancelText = '取消'
	} : {
		title : string;
		content : string;
		showCancel ?: boolean;
		confirmText ?: string;
		cancelText ?: string;
	}) : Promise<boolean> {
		return new Promise((resolve, reject) => {
			uni.showModal({
				title,
				content,
				showCancel,
				confirmText,
				cancelText,
				success: ({ confirm }) => {
					resolve(confirm);
				},
				fail: (err) => {
					reject(err);
				}
			});
		});
	}
	/**
	 * getlocation 获取当前位置经纬度
	 * @property {boolean} altitude 传入 true 会返回高度信息，由于获取高度需要较高精确度，会减慢接口返回速度
	 * @property {boolean} geocode 默认false，是否解析地址信息
	 */

	getlocation({ altitude = false, geocode = false, type = LocationType.Gcj02 } : { altitude ?: boolean; geocode ?: boolean; type : LocationType }) : Promise<any> {
		return new Promise((resolve, reject) => {
			uni.getLocation({
				altitude,
				type,
				geocode,
				success: ({ latitude, longitude }) => {
					resolve({ latitude, longitude });
				},
				fail: (err) => {
					reject(err);
				}
			});
		});
	}

	/**
	 * setlist 用作于数据加载更多或者赋值
	 * @property { Boolean } isMore 是否属于加载更多
	 * @property { Array } listData 用于存储列表数据
	 * @property { Number } total 接口数据的总条数
	 * @property { Arr+ay } listRow 接口数据条数
	 * @property { String } more 加载状态 默认 noMore
	 */
	setlist({
		isMore = false,
		listData = {},
		total = 0,
		listRow = [],
		more = {},
		pageNum = {}
	} : {
		isMore : boolean;
		listData : object;
		total : number;
		listRow : object[];
		more : object;
		pageNum : object
	}) : void {
		if (isMore) {
			if (listRow.length === 0) {
				more.value = 'noMore';
				pageNum.value--
				return;
			}
			listData.value.push(...listRow);
			more.value = 'more';
			if (listData.value.length === total) {
				more.value = 'noMore';
			}
			return;
		}
		listData.value = listRow;
		more.value = 'more';
		if (listData.value.length === total) {
			more.value = 'noMore';
		}
	}
	/**
	 * password 密码强度校验 必须包含数字和字母 密码不能低于6位数&&不能大于20位数
	 * @param {String} password 需要校验的密码字符串
	 */
	password(password : string) : boolean {
		const length = password.length;
		if (length < 6 || length > 20) {
			this.toast('请输入6-20位密码');
			return false;
		}
		const reg = /[0-9]+[a-zA-Z]+[0-9a-zA-Z]*|[a-zA-Z]+[0-9]+[0-9a-zA-Z]*/;
		if (!reg.test(password)) {
			this.toast('密码必须由数字和字母组合');
			return false;
		}
		return true;
	}
	/**
	 * copy复制功能
	 * @param {String} str 需要复制的文本内容
	 */
	copy(str : string) : void {
		// #ifdef H5
		const aux = document.createElement('input');
		aux.setAttribute('value', str);
		document.body.appendChild(aux);
		aux.select();
		document.execCommand('copy');
		document.body.removeChild(aux);
		this.toast('复制成功', 'success');
		// #endif

		// #ifndef H5
		uni.setClipboardData({
			data: str.toString()
		});
		// #endif
	}
	/**
	 * statusBar 获取手机信号栏那一块区域的高度 获取失败返回25
	 */
	statusBar() : number {
		try {
			return uni.getSystemInfoSync().statusBarHeight;
		} catch (a) {
			return 25;
		}
	}
	/**
	 * headHeight 获取原生导航栏高度，用于自定义导航栏 ios  44  android 48
	 */
	headHeight() : number {
		let h = 0;
		const platform = uni.getSystemInfoSync().platform;
		if (platform == 'ios') {
			h = 44;
		} else if (platform == 'android') {
			h = 48;
		} else {
			h = 44;
		}
		return h;
	}
	/**
	 * system 获取当前设备运行系统 返回  ios 或 android
	 */
	system() : string {
		let platform = null;
		if (uni.getSystemInfoSync().platform == 'android') {
			platform = 'android';
		}
		if (uni.getSystemInfoSync().platform == 'ios') {
			platform = 'ios';
		}
		return platform;
	}
	/**
	 * applePay 苹果支付
	 * @param data { } productid = 苹果充值产品ID , order_id = 充值订单ID
	 */
	async applePay({productid,order_id}:{productid:string,order_id:string}) : Promise<any> {
		const iapChannel = await this.getApplePay();
		if(!iapChannel) return this.toast('当前环境不支持apple支付')
		return new Promise((resolve,reject)=>{
			iapChannel.requestOrder([productid], () =>{
				this.hideloading()
				this.loading('支付中...',true)
				uni.requestPayment({
					provider: 'appleiap',
					orderInfo: {
						productid: productid,
						username: order_id
					},
					success: async (res:any) => {
						this.hideloading()
						resolve(res)
					}
				})
			}, async (err:any) =>{
				this.hideloading()
				await this.model({
					title:'温馨提示',
					content:err.message
				})
				reject(err)
			})
		})
	}
	/**
	 * getApplePay 获取苹果支付通道
	 */
	getApplePay() : Promise<any> {
		return new Promise((resolve,reject)=>{
			uni.getProvider({
				service: 'payment',
				success: (res) => {
					const iapChannel = res.providers.find((channel) => { return (channel.id === 'appleiap')})
					iapChannel ? resolve(iapChannel) : resolve(null)
				},
				fail: (err) => {
					reject(err)
				}
			});
		})
	}
	/**
	 * ailpay支付宝支付
	 * @param {String} orderInfo 支付宝支付订单数据
	 */
	ailpay(orderInfo : string) : Promise<any> {
		return new Promise((resolve, reject) => {
			uni.requestPayment({
				provider: 'alipay',
				orderInfo: orderInfo,
				success: function (res) {
					resolve(res);
				},
				fail: function (err) {
					reject(err);
				}
			});
		});
	}
	/**
	 * wxpay 发起微信支付 在小程序上面发起小程序微信支付 ，在APP发起微信支付
	 * @param {Object} orderInfo 支付参数 注意 App端，微信支付 orderInfo 为 Object 类型
	 */
	wxpay(orderInfo : string | object) : Promise<any> {
		return new Promise((resolve, reject) => {
			// #ifdef APP
			uni.requestPayment({
				provider: 'wxpay',
				orderInfo: orderInfo,
				success: (res) => {
					resolve(res);
				},
				fail: (e) => {
					this.hideloading()
					this.toast('支付失败或取消支付');
					reject(e);
				}
			});
			// #endif
			// #ifdef MP-WEIXIN
			uni.requestPayment({
				...orderInfo,
				success: function (res) {
					resolve(res);
				},
				fail: (e) => {
					this.hideloading()
					this.toast('支付失败或取消支付');
					reject(e);
				}
			});
			// #endif
		});
	}
	/**
	 * 小程序登录获取code
	 */
	getCode() : any {
		return new Promise((callback) => {
			uni.login({
				provider: 'weixin',
				success: ({ code }) => {
					callback(code);
				},
				fail: (err) => {
					console.log(err);
				}
			});
		});
	}
	/**
	 * formatTime 时间戳转换年月日  或者年月日转时间戳
	 * @property {String} timeValue 需要转换的值
	 * @property {Sgring} format 数据类型 时间戳转换年月日必传默认yyyy-mm-dd  支持如下类型 yyyy-mm-dd | yyyy年mm月dd日 | yyyy-mm-dd hh:ii:ss | hh:ii:ss
	 */
	formatTime(timeValue : number = 0, format : string = 'yyyy-mm-dd') : any {
		if (typeof timeValue === 'number') {
			const date = new Date(timeValue);
			const yyyy = date.getFullYear();
			const mm = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
			const dd = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
			const hh = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
			const ii = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
			const ss = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
			const placeholders = { yyyy, mm, dd, hh, ii, ss };
			const regex = new RegExp(Object.keys(placeholders).join('|'), 'g');
			return format.replace(regex, (match) => placeholders[match]);
		} else if (typeof timeValue === 'string') {
			if (/\d{4}-\d{2}-\d{2}/.test(timeValue)) {
				return Date.parse(timeValue);
			} else if (/\d{4}年\d{2}月\d{2}日/.test(timeValue)) {
				const [year, month, day] = timeValue.match(/\d+/g).map(Number);
				return Date.UTC(year, month - 1, day);
			} else if (/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(timeValue)) {
				return Date.parse(timeValue.replace(/-/g, '/'));
			} else {
				throw new Error('Invalid date format');
			}
		} else {
			throw new Error('Invalid time value');
		}
	}
	/**
	 * 页面跳转通用方法
	 * @property {String} url 需要跳转的链接
	 * @property {String} type=[open|close|allclose|tab|h5] 跳转的类型
	 */
	openWindow(url : string, type : string = 'open') : void {
		switch (type) {
			case 'open':
				uni.navigateTo({
					url
				});
				break;
			case 'close':
				uni.redirectTo({
					url
				});
				break;
			case 'allclose':
				uni.reLaunch({
					url
				});
				break;
			case 'tab':
				uni.switchTab({
					url
				});
				break;
			case 'h5':
				window.location.href = url;
				break;
			default:
				this.toast('请传递正确的跳转类型', 'none');
				break;
		}
	}
	/**
	 * 富文本处理
	 * @property {String} c 需要处理的富文本内容
	 */
	richtext(c : string) : string {
		try {
			c = c.replace(/<p/gi, '<p style="min-height: 22px;"');
			c = c.replace(/<img/gi, '<img style="display:block;max-width: 100%;"');
			c = c.replace(/<video/gi, '<video style="max-width: 100%;"');
			c = c.replace(/<br[^>]*\/>/gi, '');
			c = c.replace(/<td[^<>]*>/gi, '<td style="padding:0px;height:auto;word-break:break-all;">');
			c = c.replace(/<td[^<>]*>\s*?<p>/gi, '<td>');
			c = c.replace(/<th[^<>]*>\s*?<p>/gi, '<th style="width:0">');
			c = c.replace(
				/<table[^>]*>/gi,
				'<table cellpadding="0" cellspacing="0" max-width="100%" border="1" style="font-size:12px;max-width:100%; text-align:left;text-indent: 0em;line-height:12px;"'
			);
			return c;
		} catch (a) {
			return c;
		}
	}
	/**
	 * validateInput 校验手机号 身份证号  邮箱 校验失败返回false  type类型不存在则直接返回true
	 * @property { string|number } value 需要校验的值
	 * @property { string } type=[phone|idcard|email] 校验类型
	 *
	 */
	validateInput(value : string | number, type : string) : boolean {
		let regex, errorMessage;

		switch (type) {
			case 'phone':
				regex = /^1\d{10}$/;
				errorMessage = '请输入正确的手机号码';
				break;
			case 'idcard':
				regex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
				errorMessage = '请输入正确的身份证号码';
				break;
			case 'email':
				regex = /^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/;
				errorMessage = '请输入正确的电子邮件地址';
				break;
			default:
				return true;
		}

		if (regex.test(value)) {
			return true;
		} else {
			uni.showToast({ title: errorMessage, icon: 'none' });
			return false;
		}
	}
	/**
	 * updatefile 文件上传 
	 * @param {Object} e
	 */
	updatefile(e : any) {
		return new Promise((resolve, reject) => {
			const uploadTask = uni.uploadFile({
				url: `${this.url}${e.url}`,
				filePath: e.filePath,
				name: e.name,
				fileType: e.fileType ? e.fileType : 'image',
				header: {
					"Authori-zation": `Bearer ${uni.getStorageSync('token')}`
				},
				formData: {
					...e.formData
				},
				success: (res) => {
					if (res.statusCode == 200) {
						resolve(JSON.parse(res.data))
					} else {
						reject(res)
						this.model({
							title: '上传失败',
							content: JSON.stringify(res.statusCode)
						})
					}
				},
				fail: (err) => {
					reject(err)
					this.model({
						title: '上传失败fail',
						content: JSON.stringify(err)
					})
				}
			})
			uploadTask.onProgressUpdate((res) => {
				const progress = ((res.totalBytesSent / res.totalBytesExpectedToSend) * 100)
					.toFixed(0) + '%';
				e.success(res, progress)
			});
		})
	}
	/**
	 * dictType 获取数据字典 
	 * @property { string } types 字典名称
	 * @property { string } status 状态码
	 */
	dictType(types : string, status : string | number) {
		const dictlist = uni.getStorageSync('dict') || [];
		if (dictlist.length === 0) return '';
		const { dictLabel } = dictlist.filter((val) => val.dictType == types).find((val) => val.dictValue == status) || {};
		if (!dictLabel) return ''
		return dictLabel
	}
	/**
	 * formatTimestamp 时间戳转换  
	 */
	formatTimestamp(timestamp : string | number) {
		const date = new Date(timestamp);
		const year = date.getFullYear();
		const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are zero-based
		const day = String(date.getDate()).padStart(2, '0');
		const hours = String(date.getHours()).padStart(2, '0');
		const minutes = String(date.getMinutes()).padStart(2, '0');
		const seconds = String(date.getSeconds()).padStart(2, '0');
		return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
	}
	/**
	 * getServerNo 检查版本更新
	 */
	getServerNo(version, isPrompt = false, callback) {
		const httpData = {
			version_number: version.versionName
		};
		if (this.system() == 'android') {
			httpData.version_type = 2;
		} else {
			httpData.version_type = 1;
		}
		this.get({
			url: 'appUpgrade',
			data: httpData
		}).then(res => {
			if (res.data && res.data.downloadUrl) {
				if (res.data.updateType) {
					callback && callback(res.data);
				}
			} else if (isPrompt) {
				console.log('暂无新版本');
			}
		})
	}
}